package com.example.oss.validator;

import com.example.common.ResponseCode;
import com.example.common.util.ObjectUtil;
import com.example.exception.BizValidationException;
import com.example.oss.annotation.ValidFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.servlet.MultipartProperties;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.ArrayList;
import java.util.Collections;

/**
 * <h1>文件上传注解</h1>
 * @author LevelCoder
 * @version V1.0.0
 * @email LevelCoder@126.com
 * @date 2020/5/8
 */
public class MultipartFileValidator implements ConstraintValidator<ValidFile, MultipartFile[]> {

    @Autowired
    private MultipartProperties multipartProperties;

    /**
     * 上传文件最大值:当为-1时不限制大小
     */
    private long maxSize = -1;

    /**
     * 上传文件最小值
     */
    private long minSize = 0;

    /**
     * 验证文件注解
     */
    private ValidFile fileValid;

    /**
     * 延展类
     */
    private ArrayList<String> extension = new ArrayList<>();

    @Override
    public void initialize(ValidFile constraintAnnotation) {
        this.fileValid = constraintAnnotation;
        Collections.addAll(extension, fileValid.value());
        Collections.addAll(extension, fileValid.endsWith());
        if (constraintAnnotation.maxSize().equals(ValidFile.DEFAULT_MAXSIZE)) {
            this.maxSize = parseSize(multipartProperties.getMaxFileSize());
        } else {
            this.maxSize = parseSize(constraintAnnotation.maxSize());
        }
        this.minSize = parseSize(constraintAnnotation.minSize());
    }

    private long parseSize(String size) {
        Assert.hasLength(size, "Size must not be empty");
        size = size.toUpperCase();
        if (size.endsWith("KB")) {
            return Long.valueOf(size.substring(0, size.length() - 2)) * 1024;
        }
        if (size.endsWith("MB")) {
            return Long.valueOf(size.substring(0, size.length() - 2)) * 1024 * 1024;
        }
        return Long.valueOf(size);
    }

    @Override
    public boolean isValid(MultipartFile[] multipartFiles, ConstraintValidatorContext constraintValidatorContext) {
        if(ObjectUtil.isNotEmpty(multipartFiles)){
            for(MultipartFile multipartFile:multipartFiles){
                String fieldName = multipartFile.getName();
                if (multipartFile.isEmpty()) {
                    if (fileValid.allowEmpty()) {
                        return true;
                    }
                    throw new BizValidationException(ResponseCode.UPLOAD_FILES_CANNOT_BE_EMPTY.getResponseCode(), ResponseCode.UPLOAD_FILES_CANNOT_BE_EMPTY.getResponseMessage());
                }
                String originalFilename = multipartFile.getOriginalFilename();
                if (fileValid.ignoreCase()) {
                    originalFilename = originalFilename.toLowerCase();
                }
                if (extension.size() > 0 && extension.stream().noneMatch(originalFilename::endsWith)) {
                    throw new BizValidationException(ResponseCode.UPLOAD_FILE_TYPE_DOES_NOT_MATCH.getResponseCode(), ResponseCode.UPLOAD_FILE_TYPE_DOES_NOT_MATCH.getResponseMessage());
                }
                long size = multipartFile.getSize();
                if (size < this.minSize) {
                    throw new BizValidationException(ResponseCode.FILE_CANNOT_BE_LESS_THAN_MINIMUM.getResponseCode(), ResponseCode.FILE_CANNOT_BE_LESS_THAN_MINIMUM.getResponseMessage());
                }
                if (size > this.maxSize) {
                    throw new BizValidationException(ResponseCode.FILE_CANNOT_BE_GREATER_THAN_MAXIMUM.getResponseCode(), ResponseCode.FILE_CANNOT_BE_GREATER_THAN_MAXIMUM.getResponseMessage());
                }
            }
            return true;
        }else {
            throw new BizValidationException(ResponseCode.UPLOAD_FILES_CANNOT_BE_EMPTY.getResponseCode(), ResponseCode.UPLOAD_FILES_CANNOT_BE_EMPTY.getResponseMessage());
        }
    }
}
